#include <map>
#include <sstream>
#include "Channel.h"
//#include "IDatabase.h"
//#include "Database.h"
#include "Configuration.h"

//Channel::Channel(const unsigned int id, const std::string &name, const unsigned int maxNameLenght, const std::string &password, const unsigned int maxPasswordLenght, const std::string &motd, const unsigned int maxMotdLenght, const std::string &description, const unsigned int maxDescriptionLenght, const bool visible, const unsigned int maxUser, const unsigned int maxTalker)
//: _id(id), _parent(NULL), _name(name), _maxNameLenght(maxNameLenght), _password(password), _maxPasswordLenght(maxPasswordLenght), _motd(motd), _maxMotdLenght(maxMotdLenght), _description(description), _maxDescriptionLenght(maxDescriptionLenght), _visible(visible), _maxUser(maxUser), _maxTalker(maxTalker)
//{
//	/*Database::DbResult	result;
//	std::stringstream	query;
//	query << "SELECT id FROM main.channels WHERE name=\"" << name << "\" AND parentId=\"" << -1 << "\";";
//	Database::GetDatabase()->Execute(query.str(), result);*/
//	/*for (; idMapBegin != idMapEnd; ++idMapBegin)
//	{
//		if ()
//	}*/
//	/*if (result.size() == 1)
//		this->_id = result[0]->begin()->second->GetValueInt();*/
//	//else //emettre une error
//}

Channel::Channel(const unsigned int id, IChannel* parent, const std::string &name, const unsigned int maxNameLenght, const std::string &password, const unsigned int maxPasswordLenght, const std::string &motd, const unsigned int maxMotdLenght, const std::string &description, const unsigned int maxDescriptionLenght, const bool visible, const unsigned int maxUser, const unsigned int maxTalker)
: _id(id), _parent(parent), _name(name), _maxNameLenght(maxNameLenght), _password(password), _maxPasswordLenght(maxPasswordLenght), _motd(motd), _maxMotdLenght(maxMotdLenght), _description(description), _maxDescriptionLenght(maxDescriptionLenght), _visible(visible), _maxUser(maxUser), _maxTalker(maxTalker)
{
	//Database::DbResult	result;
	//std::stringstream	query;
	//query << "SELECT id FROM main.channels WHERE name=\"" << name << "\" AND parentId=\"" << parent->GetId() << "\";";
	//Database::GetDatabase()->Execute(query.str(), result);
	///*for (; idMapBegin != idMapEnd; ++idMapBegin)
	//{
	//	if ()
	//}*/
	//if (result.size() == 1)
	//	this->_id = result[0]->begin()->second->GetValueInt();
}

Channel::~Channel(void)
{
}

const unsigned int	Channel::GetId(void) const
{
	return this->_id;
}

// methode dangereuse, normalement on set pas l'id, il est determine par database, sauf cas ou ca devient un main channel on doit set a -1
const unsigned int	Channel::SetId(const unsigned int id)
{
	// faire le changement dans la base
	this->_id = id;
	return 0;
}

IChannel*	Channel::GetParent(void) const
{
	return this->_parent;
}

const unsigned int	Channel::SetParent(IChannel* parent)
{
	//changement dans la base
	Configuration::GetConfiguration()->GetDatabase()->UpdateChannelIdParent(this->_id, parent->GetId());
	//changement dans le server
	if (this->_parent)
		this->_parent->RemoveChannelChild(this);
	this->_parent = parent;
	this->_parent->AddChannelChild(this);
	return 0;
}

// impossible d'utiliser ces methodes car on ne peut pas include le channel manager dans la classe channel
//const unsigned int	Channel::SetParent(const unsigned int id)
//{
//	if (this->_parent)
//		this->_parent->RemoveChannelChild(this);
//	//this->_parent = channelManager->GetChannel(id);
//	this->_parent->AddChannelChild(this);
//	return 0;
//}
//
//const unsigned int	Channel::SetParent(const std::string& pattern)
//{
//	if (this->_parent)
//		this->_parent->RemoveChannelChild(this);
//	//this->_parent = channelManager->GetChannel(pattern);
//	this->_parent->AddChannelChild(this);
//	return 0;
//}

//const unsigned int	Channel::UnSetParent(void)
//{
//	if (this->HaveParent())
//	{
//		//changement dans la base
//		/*std::stringstream	query;
//		query << "UPDATE main.channels SET parentId=-1" << " WHERE parentId=" << this->_parent->GetId() << " AND name=" << this->_name << ";";
//		Database::GetDatabase()->Execute(query.str());*/
//		if (this->_parent)
//			this->_parent->RemoveChannelChild(this);
//		this->_parent = NULL;
//	}
//	return 0;
//}

const bool	Channel::HaveParent(void) const
{
	if (this->_parent)
		return true;
	return false;
}

const std::string&	Channel::GetName(void) const
{
	return this->_name;
}

const unsigned int	Channel::SetName(const std::string& name)
{
	//changement dans la base
	Configuration::GetConfiguration()->GetDatabase()->UpdateChannelName(this->_id, name);
	this->_name = name;
	return 0;
}

const unsigned int	Channel::GetMaxNameLength(void) const
{
	return this->_maxNameLenght;
}

const unsigned int	Channel::SetMaxNameLength(const unsigned int length, bool recurcive)
{
	if (recurcive)
	{
		std::list<IChannel*>::iterator	iteCurrent = this->_child.begin();
		std::list<IChannel*>::iterator	iteEnd = this->_child.end();
		while (iteCurrent != iteEnd)
		{
			(*iteCurrent)->SetMaxNameLength(length, true);
			++iteCurrent;
		}
	}
	//changement dans la base
	Configuration::GetConfiguration()->GetDatabase()->UpdateChannelMaxNameLenght(this->_id, length);
	this->_maxNameLenght = length;
	return 0;
}

const std::string&	Channel::GetPassword(void) const
{
	return this->_password;
}

const unsigned int	Channel::SetPassword(const std::string& password, bool recurcive)
{
	if (recurcive)
	{
		std::list<IChannel*>::iterator	iteCurrent = this->_child.begin();
		std::list<IChannel*>::iterator	iteEnd = this->_child.end();
		while (iteCurrent != iteEnd)
		{
			(*iteCurrent)->SetPassword(password, true);
			++iteCurrent;
		}
	}
	//changement dans la base
	Configuration::GetConfiguration()->GetDatabase()->UpdateChannelPassword(this->_id, password);
	this->_password = password;
	return 0;
}

const unsigned int	Channel::GetMaxPasswordLength(void) const
{
	return this->_maxPasswordLenght;
}

const unsigned int	Channel::SetMaxPasswordLength(const unsigned int length, bool recurcive)
{
	if (recurcive)
	{
		std::list<IChannel*>::iterator	iteCurrent = this->_child.begin();
		std::list<IChannel*>::iterator	iteEnd = this->_child.end();
		while (iteCurrent != iteEnd)
		{
			(*iteCurrent)->SetMaxPasswordLength(length, true);
			++iteCurrent;
		}
	}
	//changement dans la base
	Configuration::GetConfiguration()->GetDatabase()->UpdateChannelMaxPasswordLenght(this->_id, length);
	this->_maxPasswordLenght = length;
	return 0;
}

const std::string&	Channel::GetMotd(void) const
{
	return this->_motd;
}

const unsigned int	Channel::SetMotd(const std::string& motd, bool recurcive)
{
	if (recurcive)
	{
		std::list<IChannel*>::iterator	iteCurrent = this->_child.begin();
		std::list<IChannel*>::iterator	iteEnd = this->_child.end();
		while (iteCurrent != iteEnd)
		{
			(*iteCurrent)->SetMotd(motd, true);
			++iteCurrent;
		}
	}
	//changement dans la base
	Configuration::GetConfiguration()->GetDatabase()->UpdateChannelMotd(this->_id, motd);
	this->_motd = motd;
	return 0;
}

const unsigned int	Channel::GetMaxMotdLength(void) const
{
	return this->_maxMotdLenght;
}

const unsigned int	Channel::SetMaxMotdLength(const unsigned int length, bool recurcive)
{
	if (recurcive)
	{
		std::list<IChannel*>::iterator	iteCurrent = this->_child.begin();
		std::list<IChannel*>::iterator	iteEnd = this->_child.end();
		while (iteCurrent != iteEnd)
		{
			(*iteCurrent)->SetMaxMotdLength(length, true);
			++iteCurrent;
		}
	}
	//changement dans la base
	Configuration::GetConfiguration()->GetDatabase()->UpdateChannelMaxMotdLenght(this->_id, length);
	this->_maxMotdLenght = length;
	return 0;
}

const std::string&	Channel::GetDescription(void) const
{
	return this->_description;
}

const unsigned int	Channel::SetDescription(const std::string& description, bool recurcive)
{
	if (recurcive)
	{
		std::list<IChannel*>::iterator	iteCurrent = this->_child.begin();
		std::list<IChannel*>::iterator	iteEnd = this->_child.end();
		while (iteCurrent != iteEnd)
		{
			(*iteCurrent)->SetDescription(description, true);
			++iteCurrent;
		}
	}
	//changement dans la base
	Configuration::GetConfiguration()->GetDatabase()->UpdateChannelDescription(this->_id, description);
	this->_description = description;
	return 0;
}

const unsigned int	Channel::GetMaxDescriptionLength(void) const
{
	return this->_maxDescriptionLenght;
}

const unsigned int	Channel::SetMaxDescriptionLength(const unsigned int length, bool recurcive)
{
	if (recurcive)
	{
		std::list<IChannel*>::iterator	iteCurrent = this->_child.begin();
		std::list<IChannel*>::iterator	iteEnd = this->_child.end();
		while (iteCurrent != iteEnd)
		{
			(*iteCurrent)->SetMaxDescriptionLength(length, true);
			++iteCurrent;
		}
	}
	//changement dans la base
	Configuration::GetConfiguration()->GetDatabase()->UpdateChannelMaxDesciptionLenght(this->_id, length);
	this->_maxDescriptionLenght = length;
	return 0;
}

const bool			Channel::GetVisibility(void) const
{
	return this->_visible;
}

const unsigned int	Channel::SetVisibility(const bool visible, bool recurcive)
{
	if (recurcive)
	{
		std::list<IChannel*>::iterator	iteCurrent = this->_child.begin();
		std::list<IChannel*>::iterator	iteEnd = this->_child.end();
		while (iteCurrent != iteEnd)
		{
			(*iteCurrent)->SetVisibility(visible, true);
			++iteCurrent;
		}
	}
	//changement dans la base
	Configuration::GetConfiguration()->GetDatabase()->UpdateChannelVisibility(this->_id, visible);
	this->_visible = visible;
	return 0;
}

const unsigned int	Channel::GetMaxUser(void) const
{
	return this->_maxUser;
}

const unsigned int	Channel::SetMaxUser(const unsigned int limit, bool recurcive)
{
	if (recurcive)
	{
		std::list<IChannel*>::iterator	iteCurrent = this->_child.begin();
		std::list<IChannel*>::iterator	iteEnd = this->_child.end();
		while (iteCurrent != iteEnd)
		{
			(*iteCurrent)->SetMaxUser(limit, true);
			++iteCurrent;
		}
	}
	//changement dans la base
	Configuration::GetConfiguration()->GetDatabase()->UpdateChannelMaxUser(this->_id, limit);
	this->_maxUser = limit;
	return 0;
}

const unsigned int	Channel::GetMaxTalker(void) const
{
	return this->_maxTalker;
}

const unsigned int	Channel::SetMaxTalker(const unsigned int limit, bool recurcive)
{
	if (recurcive)
	{
		std::list<IChannel*>::iterator	iteCurrent = this->_child.begin();
		std::list<IChannel*>::iterator	iteEnd = this->_child.end();
		while (iteCurrent != iteEnd)
		{
			(*iteCurrent)->SetMaxTalker(limit, true);
			++iteCurrent;
		}
	}
	//changement dans la base
	Configuration::GetConfiguration()->GetDatabase()->UpdateChannelMaxTalker(this->_id, limit);
	this->_maxTalker = limit;
	return 0;
}
// WARNING : pourquoi pas virer cette methode et obliger a passer par le channel manager
// ca permet de faire propre au niveau de delete et du deplacement des users
const unsigned int	Channel::DeleteChannel(void)
{
	//changement dans la base
	Configuration::GetConfiguration()->GetDatabase()->DeleteChannel(this->_id);
	
	return 0;
}

const unsigned int	Channel::AddChannelChild(IChannel* channel)
{
	this->_child.push_back(channel);
	return 0;
}

const unsigned int	Channel::RemoveChannelChild(IChannel* channel)
{
	this->_child.remove(channel);
	return 0;
}

// WARNING : renvoyer en ref ou ptr ?
//std::list<IChannel*>&	Channel::GetChannelChild(void) const
//{
//	std::list<IChannel*>* lst = new std::list<IChannel*>();
//	*lst = this->_child;
//	return *lst;
//}

std::list<IChannel*>*	Channel::GetChannelChild(void)
{
	return &(this->_child);
}

const unsigned int	Channel::AddUser(IUser* user)
{
	this->_user.push_back(user);
	return 0;
}

const unsigned int	Channel::RemoveUser(IUser* user)
{
	this->_user.remove(user);
	return 0;
}

const unsigned int	Channel::SubscribeUser(IUser*, IChannelRight*)
{
	return 0;
}

const unsigned int	Channel::UnSubscribeUser(IUser*)
{
	return 0;
}
// WARNING : renvoyer en ref ou ptr ?
//std::list<IUser*>&	Channel::GetUser() const
//{
//	std::list<IUser*>*	lst = new std::list<IUser*>();
//	*lst = this->_user;
//	return *lst;
//}

std::list<IUser*>*	Channel::GetUser()
{
	return &(this->_user);
}
